home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 May / EnigmA AMIGA RUN 18 (1997)(G.R. Edizioni)(IT)[!][issue 1997-05][EAR-CD II].iso / earcd / mus / play / mikmod.lzh / mikmod / load_mod.c < prev    next >
C/C++ Source or Header  |  1997-01-28  |  8KB  |  359 lines

  1. /*
  2.  
  3. Name:
  4. LOAD_MOD.C
  5.  
  6. Description:
  7. Generic MOD loader
  8.  
  9. Portability:
  10. All systems - all compilers (hopefully)
  11.  
  12. */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17. #include "mikmod.h"
  18.  
  19. /*************************************************************************
  20. *************************************************************************/
  21.  
  22.  
  23. typedef struct MSAMPINFO{       /* sample header as it appears in a module */
  24.     UBYTE samplename[22];
  25.     UWORD length;
  26.     UBYTE finetune;
  27.     UBYTE volume;
  28.     UWORD reppos;
  29.     UWORD replen;
  30. } MSAMPINFO;
  31.  
  32.  
  33. typedef struct MODULEHEADER{    /* verbatim module header */
  34.     UBYTE      songname[20];                /* the songname.. */
  35.     MSAMPINFO  samples[31];                         /* all sampleinfo */
  36.     UBYTE      songlength;                          /* number of patterns used */
  37.     UBYTE      magic1;                                      /* should be 127 */
  38.     UBYTE      positions[128];                      /* which pattern to play at pos */
  39.     UBYTE      magic2[4];                           /* string "M.K." or "FLT4" or "FLT8" */
  40. } MODULEHEADER;
  41.  
  42. #define MODULEHEADERSIZE 1084
  43.  
  44.  
  45. typedef struct MODTYPE{                         /* struct to identify type of module */
  46.     char    id[4];
  47.     UBYTE   channels;
  48.     char    *name;
  49. } MODTYPE;
  50.  
  51.  
  52. typedef struct MODNOTE{
  53.     UBYTE a,b,c,d;
  54. } MODNOTE;
  55.  
  56.  
  57. /*************************************************************************
  58. *************************************************************************/
  59.  
  60.  
  61. char protracker[]="Protracker";
  62. char startracker[]="Startracker";
  63. char fasttracker[]="Fasttracker";
  64. char ins15tracker[]="15-instrument";
  65. char oktalyzer[]="Oktalyzer";
  66. char taketracker[]="TakeTracker";
  67.  
  68.  
  69. MODTYPE modtypes[]={
  70.     "M.K.",4,protracker,    /* protracker 4 channel */
  71.     "M!K!",4,protracker,    /* protracker 4 channel */
  72.     "FLT4",4,startracker,   /* startracker 4 channel */
  73.     "4CHN",4,fasttracker,   /* fasttracker 4 channel */
  74.     "6CHN",6,fasttracker,   /* fasttracker 6 channel */
  75.     "8CHN",8,fasttracker,   /* fasttracker 8 channel */
  76.     "CD81",8,oktalyzer,     /* atari oktalyzer 8 channel */
  77.     "OKTA",8,oktalyzer,     /* atari oktalyzer 8 channel */
  78.     "16CN",16,taketracker,  /* taketracker 16 channel */
  79.     "32CN",32,taketracker,  /* taketracker 32 channel */
  80.     "    ",4,ins15tracker   /* 15-instrument 4 channel */
  81. };
  82.  
  83. static MODULEHEADER *mh;        /* raw as-is module header */
  84. static MODNOTE *patbuf;
  85.  
  86.  
  87. BOOL MOD_Test(void)
  88. {
  89.     int t;
  90.  
  91.     char id[4];
  92.  
  93.     _mm_fseek(modfp,MODULEHEADERSIZE-4,SEEK_SET);
  94.     if(!fread(id,4,1,modfp)) return 0;
  95.  
  96.     /* find out which ID string */
  97.  
  98.     for(t=0;t<10;t++){
  99.         if(!memcmp(id,modtypes[t].id,4)) return 1;
  100.     }
  101.  
  102.     return 0;
  103. }
  104.  
  105.  
  106. BOOL MOD_Init(void)
  107. {
  108.     patbuf=NULL;
  109.     if(!(mh=MyCalloc(1,sizeof(MODULEHEADER)))) return 0;
  110.     return 1;
  111. }
  112.  
  113.  
  114. void MOD_Cleanup(void)
  115. {
  116.     if(mh!=NULL) free(mh);
  117.     if(patbuf!=NULL) free(patbuf);
  118. }
  119.  
  120.  
  121. /*
  122.  
  123. Old (amiga) noteinfo:
  124.  
  125.  _____byte 1_____   byte2_    _____byte 3_____   byte4_
  126. /                \ /      \  /                \ /      \
  127. 0000          0000-00000000  0000          0000-00000000
  128.  
  129. Upper four    12 bits for    Lower four    Effect command.
  130. bits of sam-  note period.   bits of sam-
  131. ple number.                  ple number.
  132.  
  133.  
  134. */
  135.  
  136.  
  137. UWORD npertab[60]={
  138.  
  139. /* -> Tuning 0 */
  140.  
  141.     1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
  142.     856,808,762,720,678,640,604,570,538,508,480,453,
  143.     428,404,381,360,339,320,302,285,269,254,240,226,
  144.     214,202,190,180,170,160,151,143,135,127,120,113,
  145.     107,101,95,90,85,80,75,71,67,63,60,56
  146. };
  147.  
  148.  
  149. void ConvertNote(MODNOTE *n)
  150. {
  151.     UBYTE instrument,effect,effdat,note;
  152.     UWORD period;
  153.  
  154.     /* extract the various information from the 4 bytes that
  155.        make up a single note */
  156.  
  157.     instrument=(n->a&0x10)|(n->c>>4);
  158.     period=(((UWORD)n->a&0xf)<<8)+n->b;
  159.     effect=n->c&0xf;
  160.     effdat=n->d;
  161.  
  162.     /* Convert the period to a note number */
  163.  
  164.     note=0;
  165.     if(period!=0){
  166.         for(note=0;note<60;note++){
  167.             if(period>=npertab[note]) break;
  168.         }
  169.         note++;
  170.         if(note==61) note=0;
  171.     }
  172.  
  173.     if(instrument!=0){
  174.         UniInstrument(instrument-1);
  175.     }
  176.  
  177.     if(note!=0){
  178.         UniNote(note+23);
  179.     }
  180.  
  181.     UniPTEffect(effect,effdat);
  182. }
  183.  
  184.  
  185. UBYTE *ConvertTrack(MODNOTE *n)
  186. {
  187.     int t;
  188.  
  189.     UniReset();
  190.     for(t=0;t<64;t++){
  191.         ConvertNote(n);
  192.         UniNewline();
  193.         n+=of.numchn;
  194.     }
  195.     return UniDup();
  196. }
  197.  
  198.  
  199. BOOL ML_LoadPatterns(void)
  200. /*
  201.     Loads all patterns of a modfile and converts them into the
  202.     3 byte format.
  203. */
  204. {
  205.     int t,s,tracks=0;
  206.  
  207.     if(!AllocPatterns()) return 0;
  208.     if(!AllocTracks()) return 0;
  209.  
  210.     /* Allocate temporary buffer for loading
  211.        and converting the patterns */
  212.  
  213.     if(!(patbuf=MyCalloc(64U*of.numchn,sizeof(MODNOTE)))) return 0;
  214.  
  215.     for(t=0;t<of.numpat;t++){
  216.  
  217.         /* Load the pattern into the temp buffer
  218.            and convert it */
  219.  
  220.         for(s=0;s<(64U*of.numchn);s++){
  221.             patbuf[s].a=_mm_read_UBYTE(modfp);
  222.             patbuf[s].b=_mm_read_UBYTE(modfp);
  223.             patbuf[s].c=_mm_read_UBYTE(modfp);
  224.             patbuf[s].d=_mm_read_UBYTE(modfp);
  225.         }
  226.  
  227.         for(s=0;s<of.numchn;s++){
  228.             if(!(of.tracks[tracks++]=ConvertTrack(patbuf+s))) return 0;
  229.         }
  230.     }
  231.  
  232.     return 1;
  233. }
  234.  
  235.  
  236. BOOL MOD_Load(void)
  237. {
  238.     int t,modtype;
  239.     INSTRUMENT *d;          /* new sampleinfo structure */
  240.     SAMPLE *q;
  241.     MSAMPINFO *s;           /* old module sampleinfo */
  242.  
  243.     /* try to read module header */
  244.  
  245.     _mm_read_str(mh->songname,20,modfp);
  246.  
  247.     for(t=0;t<31;t++){
  248.         s=&mh->samples[t];
  249.         _mm_read_str(s->samplename,22,modfp);
  250.         s->length    =_mm_read_M_UWORD(modfp);
  251.         s->finetune    =_mm_read_UBYTE(modfp);
  252.         s->volume    =_mm_read_UBYTE(modfp);
  253.         s->reppos    =_mm_read_M_UWORD(modfp);
  254.         s->replen    =_mm_read_M_UWORD(modfp);
  255.     }
  256.  
  257.     mh->songlength    =_mm_read_UBYTE(modfp);
  258.     mh->magic1        =_mm_read_UBYTE(modfp);
  259.  
  260.     _mm_read_UBYTES(mh->positions,128,modfp);
  261.     _mm_read_UBYTES(mh->magic2,4,modfp);
  262.  
  263.     if(feof(modfp)){
  264.         myerr=ERROR_LOADING_HEADER;
  265.         return 0;
  266.     }
  267.  
  268.     /* find out which ID string */
  269.  
  270.     for(modtype=0;modtype<10;modtype++){
  271.         if(!memcmp(mh->magic2,modtypes[modtype].id,4)) break;
  272.     }
  273.  
  274.     if(modtype==10){
  275.  
  276.         /* unknown modtype */
  277.         myerr=ERROR_NOT_A_MODULE;
  278.         return 0;
  279.     }
  280.  
  281.     /* set module variables */
  282.  
  283.     of.initspeed=6;
  284.     of.inittempo=125;
  285.     of.numchn=modtypes[modtype].channels;      /* get number of channels */
  286.     of.modtype=strdup(modtypes[modtype].name);      /* get ascii type of mod */
  287.     of.songname=DupStr(mh->songname,20);            /* make a cstr of songname */
  288.     of.numpos=mh->songlength;               /* copy the songlength */
  289.     memcpy(of.positions,mh->positions,128);         /* copy the position array */
  290.  
  291.     /* Count the number of patterns */
  292.  
  293.     of.numpat=0;
  294.  
  295.     for(t=0;t<128;t++){             /* <-- BUGFIX... have to check ALL positions */
  296.         if(of.positions[t] > of.numpat){
  297.             of.numpat=of.positions[t];
  298.         }
  299.     }
  300.     of.numpat++;
  301.     of.numtrk=of.numpat*of.numchn;
  302.  
  303.     /* Finally, init the sampleinfo structures */
  304.  
  305.     of.numins=31;
  306.  
  307.     if(!AllocInstruments()) return 0;
  308.  
  309.     s=mh->samples;   /* init source pointer */
  310.     d=of.instruments;  /* init dest pointer */
  311.  
  312.     for(t=0;t<of.numins;t++){
  313.  
  314.         d->numsmp=1;
  315.         if(!AllocSamples(d)) return 0;
  316.  
  317.         q=d->samples;
  318.  
  319.         /* convert the samplename */
  320.  
  321.         d->insname=DupStr(s->samplename,22);
  322.  
  323.         /* init the sampleinfo variables and
  324.            convert the size pointers to longword format */
  325.  
  326.         q->c2spd=finetune[s->finetune&0xf];
  327.         q->volume=s->volume;
  328.         q->loopstart=(ULONG)s->reppos<<1;
  329.         q->loopend=q->loopstart+((ULONG)s->replen<<1);
  330.         q->length=(ULONG)s->length<<1;
  331.         q->seekpos=0;
  332.  
  333.         q->flags=SF_SIGNED;
  334.         if(s->replen>1) q->flags|=SF_LOOP;
  335.  
  336.         /* fix replen if repend>length */
  337.  
  338.         if(q->loopend>q->length) q->loopend=q->length;
  339.  
  340.         s++;    /* point to next source sampleinfo */
  341.         d++;    /* point to next destiny sampleinfo */
  342.     }
  343.  
  344.     if(!ML_LoadPatterns()) return 0;
  345.     return 1;
  346. }
  347.  
  348.  
  349.  
  350. LOADER load_mod={
  351.     NULL,
  352.     "Standard module",
  353.     "Portable MOD loader v0.11",
  354.     MOD_Init,
  355.     MOD_Test,
  356.     MOD_Load,
  357.     MOD_Cleanup
  358. };
  359.